package pro.cherish.knowledgedemoaop.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author 创建人：cherish
 * @version 版本号：V1.0
 * <p>
 * ***************************修订记录************************************
 * 2019-09-28 cherish 创建该类功能。
 * **********************************************************************
 * </p>
 * @ClassName 类名：WebLogAcpect2
 * @Description 功能说明：
 * <p>
 * TODO
 * </p>
 * **********************************************************************
 * @date 创建日期： 2019-09-28 cherish
 */
@Aspect
@Component
@Slf4j
public class WebLogAcpect3 {
    /**
     * 定义切入点，切入点为com.example.aop下的所有函数
     */
    @Pointcut("execution(public * pro.cherish.knowledgedemoaop.controller.Tcontroller3.*(..))")
    public void webLog() {
    }

    /**
     * 后置异常通知
     * 定义一个名字，该名字用于匹配通知实现方法的一个参数名，当目标方法抛出异常返回后，将把目标方法抛出的异常传给通知方法；
     * throwing:限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知，否则不执行，
     * 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
     *
     * @param joinPoint
     * @param exception
     */
    @AfterThrowing(value = "webLog()", throwing = "exception")
    public void doAfterThrowingAdvice(JoinPoint joinPoint, Throwable exception) {
        //目标方法名：  
        log.info(joinPoint.getSignature().getName());
        if (exception instanceof NullPointerException) {
            log.info("发生了空指针异常!!!!!");
        }
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        //创建时间
        log.error("dateTime={}" + dateFormat.format(new Date()));
        //URL
        log.error("url={}", request.getRequestURL());
        //method
        log.error("method={}", request.getMethod());
        //ip
        log.error("ip={}", request.getRemoteAddr());
        //class_method
        log.error("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "," + joinPoint.getSignature().getName());
        //args[]
        log.error("args={}", joinPoint.getArgs());
        //异常信息
        log.error("errMessage={}" + exception.getMessage());
    }


    /**
     * 有异常执行后，不会return，所有直接不执行此处
     * @param joinPoint
     * @param keys
     */
    @AfterReturning(value = "webLog()", returning = "keys")
    public void doAfterReturningAdvice1(JoinPoint joinPoint, Object keys) {
        log.info("第一个后置返回通知的返回值：" + keys);
    }

    /**
     * 后置最终通知（目标方法只要执行完了就会执行后置通知方法） 【如果有@AfterThrowing，在@AfterThrowing之前执行】
     * @param joinPoint
     */
    @After(value = "webLog()")
    public void doAfterAdvice(JoinPoint joinPoint){
        log.info("后置最终通知执行了!!!!");
    }
}
